package com.giantlizard.cloud.common.security.utils;

import com.giantlizard.cloud.common.security.constants.SecurityConstants;
import com.giantlizard.cloud.common.security.model.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 */
public class JwtTokenUtil {
    
    /** Token中的权限声明 */
    private static final String CLAIM_KEY_AUTHORITIES = "authorities";
    /** Token中的用户ID声明 */
    private static final String CLAIM_KEY_USER_ID = "userId";
    /** Token中的用户名声明 */
    private static final String CLAIM_KEY_USERNAME = "username";
    /** Token中的机构ID声明 */
    private static final String CLAIM_KEY_ORG_ID = "orgId";
    
    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    private static String createToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET)
                .compact();
    }
    
    /**
     * 从令牌中获取数据声明
     *
     * @param token 令牌
     * @return 数据声明
     */
    private static Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(SecurityConstants.SECRET)
                .parseClaimsJws(token)
                .getBody();
    }
    
    /**
     * 生成令牌
     *
     * @param loginUser 用户信息
     * @return 令牌
     */
    public static String generateToken(LoginUser loginUser) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_USER_ID, loginUser.getUserId());
        claims.put(CLAIM_KEY_USERNAME, loginUser.getUsername());
        claims.put(CLAIM_KEY_AUTHORITIES, loginUser.getPermissions());
        claims.put(CLAIM_KEY_ORG_ID, loginUser.getOrgId());
        return createToken(claims);
    }
    
    /**
     * 从令牌中获取用户ID
     *
     * @param token 令牌
     * @return 用户ID
     */
    public static String getUserIdFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.get(CLAIM_KEY_USER_ID).toString();
    }
    
    /**
     * 从令牌中获取用户名
     *
     * @param token 令牌
     * @return 用户名
     */
    public static String getUsernameFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.get(CLAIM_KEY_USERNAME).toString();
    }
    
    /**
     * 验证令牌有效期
     *
     * @param token 令牌
     * @return 是否有效
     */
    public static boolean validateToken(String token) {
        try {
            Claims claims = parseToken(token);
            return !claims.getExpiration().before(new Date());
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 获取请求token
     *
     * @param request 请求对象
     * @return token令牌
     */
    public static String getToken(HttpServletRequest request) {
        String token = request.getHeader(SecurityConstants.AUTHENTICATION);
        if (StringUtils.hasText(token) && token.startsWith(SecurityConstants.PREFIX)) {
            token = token.substring(SecurityConstants.PREFIX.length());
        }
        return token;
    }
} 